package org.notabug.lifeuser.moviedb;

import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import java.util.ArrayList;

public class CastActivity extends BaseActivity
		implements NavigationView.OnNavigationItemSelectedListener {

	private RecyclerView movieView;
	private SimilarMovieBaseAdapter similarMovieAdapter;
	private ArrayList<JSONObject> similarMovieArrayList;

	private Drawable mToolbarBackgroundDrawable;
	private Toolbar toolbar;

	private int actorId;
	private String actorImageId;

	private ImageView actorImage;
	private TextView actorName;
	private ImageView actorIcon;
	private TextView actorPlaceOfBirth;
	private TextView actorBirthday;
	private TextView actorBiography;

	/*
	* This class provides an overview for actors. 
	* The data is send via an Intent that comes from the DetailActivity
	* DetailActivity in his turn gets the data from the CastBaseAdapter
	*/

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_cast);	
		setNavigationDrawer();

		// Set a transparent background that becomes less transparent
		// when scrolling down.
		mToolbarBackgroundDrawable = new ColorDrawable(ContextCompat
				.getColor(getApplicationContext(), R.color.colorPrimary));
		mToolbarBackgroundDrawable.setAlpha(0);
		
		toolbar = (Toolbar) findViewById(R.id.toolbar);
		toolbar.setBackgroundDrawable(mToolbarBackgroundDrawable);

		// Make the transparency dependent on how far the user scrolled down.
		NotifyingScrollView notifyingScrollView = (NotifyingScrollView) 
				findViewById(R.id.castScrollView);
		notifyingScrollView.setOnScrollChangedListener(mOnScrollChangedListener);

		if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
			mToolbarBackgroundDrawable.setCallback(drawableCallback);
		}

		// RecyclerView to display the movies that an actor has played in.
		movieView = (RecyclerView) findViewById(R.id.movieRecyclerView);
		movieView.setHasFixedSize(true);

		LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
		movieView.setLayoutManager(linearLayoutManager);

		// Get the intent, get the JSONObject string and convert it back.
		// Send the JSONObject to the setActorData method so all the data
		// will be displayed on the screen.
		Intent intent = getIntent();
		try {
			setActorData(new JSONObject(intent.getStringExtra(("actorObject"))));

			similarMovieArrayList = new ArrayList<JSONObject>();
			similarMovieAdapter = new SimilarMovieBaseAdapter(similarMovieArrayList,
					getApplicationContext());
			movieView.setAdapter(similarMovieAdapter);
		} catch(JSONException e) {
			e.printStackTrace();
		}

		// Get the movies the actor played in
		new ActorMovieList().execute();

		// Load actor details
		new ActorDetails().execute();
	}

	private void setActorData(JSONObject actorObject) {

		// Get the views from the layout
		actorImage = (ImageView) findViewById(R.id.actorImage);
		actorName = (TextView) findViewById(R.id.actorName);
		actorIcon = (ImageView) findViewById(R.id.actorIcon);
		actorPlaceOfBirth = (TextView) findViewById(R.id.actorPlaceOfBirth);
		actorBirthday = (TextView) findViewById(R.id.actorBirthday);
		actorBiography = (TextView) findViewById(R.id.actorBiography);

		// Check if actorObject values differ from the current values,
		// if they do, use the actorObject values.
		try {
			// Set the actorId
			if(actorObject.has("id")) {
				actorId = Integer.parseInt(actorObject.getString("id"));
			}

			// Due to the difficulty of comparing images (or rather,
			// this can be a really slow process) the id of the image is
			// saved as class variable for easy comparison.
			if(actorObject.has("profile_path") && 
					!actorObject.getString("profile_path").equals(actorImageId)) {
				Picasso.with(this).load("https://image.tmdb.org/t/p/w320" + 
						actorObject.getString("profile_path"))
						.into(actorImage); 
				Picasso.with(this).load("https://image.tmdb.org/t/p/w154" + 
						actorObject.getString("profile_path"))
						.into(actorIcon);

				// Set the old imageId to the new one.
				actorImageId = actorObject.getString("profile_path");
			}

			// If the name is different in the new dataset, change it.
			if(actorObject.has("name") && !actorObject.getString("name").equals(actorName.getText().toString())) {
				actorName.setText(actorObject.getString("name"));
			}

			// If the place of birth is different in the new dataset, change it.
			if(actorObject.has("place_of_birth") && !actorObject.getString("place_of_birth").equals(actorPlaceOfBirth
						.getText().toString())) {
				actorPlaceOfBirth.setText(getString(R.string.place_of_birth) + actorObject.getString("place_of_birth"));
			}

			// If the birthday is different in the new dataset, change it.
			if(actorObject.has("birthday") && !actorObject.getString("birthday").equals(actorBirthday
						.getText().toString())) {
				actorBirthday.setText(getString(R.string.birthday) + actorObject.getString("birthday"));
			}

			// If the biography is different in the new dataset, change it.
			if(actorObject.has("biography") && 
					!actorObject.getString("biography").equals(
					actorBiography.getText().toString())) {
				actorBiography.setText(actorObject.getString("biography"));
				if(actorObject.getString("biography").equals("")) {
					actorBiography.setText(getString(R.string.no_biography) + actorObject.getString("name") + ".");
				}
			}
		} catch(JSONException e) {
			e.printStackTrace();
		}
	}

	// Change transparency when scrolling.
	private NotifyingScrollView.OnScrollChangedListener
			mOnScrollChangedListener = new NotifyingScrollView
			.OnScrollChangedListener() {
		public void onScrollChanged(ScrollView scrollView, int l, int t, int oldl, int oldt) {
			final int headerHeight = findViewById(R.id.actorImage).getHeight() - 
					toolbar.getHeight();
			final float ratio = (float) Math.min(Math.max(t, 0), headerHeight) / headerHeight;
			final int newAlpha = (int) (ratio * 255);
			mToolbarBackgroundDrawable.setAlpha(newAlpha);
		}
	};

	// Old way to set the background.
	private Drawable.Callback drawableCallback = new Drawable.Callback() {
		@Override
		public void invalidateDrawable(Drawable drawable) {
			toolbar.setBackgroundDrawable(drawable);
		}

		@Override
		public void scheduleDrawable(Drawable drawable, Runnable runnable, long when) {}

		@Override
		public void unscheduleDrawable(Drawable drawable, Runnable runnable) {}
	};

	// Load the actor's movies.
	private class ActorMovieList extends AsyncTask<String, Void, String> {

		private final String API_KEY = ConfigHelper.getConfigValue(getApplicationContext(), "api_key");

		protected String doInBackground(String... params) {
			String line;
			StringBuilder stringBuilder = new StringBuilder();

			// Load the webpage with the actor's movies.
			try {
				URL url = new URL("https://api.themoviedb.org/3/person/" +
						actorId +"/combined_credits?api_key=" + API_KEY + getLanguageParameter());
				URLConnection urlConnection = url.openConnection();

				try {
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(
							urlConnection.getInputStream()));

					// Create one long string of the webpage.
					while((line = bufferedReader.readLine()) != null) {
						stringBuilder.append(line).append("\n");
					}

					// Close connection and return the data from the webpage.
					bufferedReader.close();
					return stringBuilder.toString();
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			} catch(MalformedURLException mue) {
				mue.printStackTrace();
			} catch(IOException ioe) {
				ioe.printStackTrace();
			}

			// Loading the dataset failed, return null.
			return null;
		}

		protected void onPostExecute(String response) {
			// Break the JSON dataset down and add the JSONObjects to the array.
			try {
				JSONObject reader = new JSONObject(response);
				JSONArray similarMovieArray = reader.getJSONArray("cast");
				for(int i = 0; i < similarMovieArray.length(); i++) {
					JSONObject actorMovies = similarMovieArray.getJSONObject(i);
					similarMovieArrayList.add(actorMovies);
				}
				similarMovieAdapter = new SimilarMovieBaseAdapter(
						similarMovieArrayList, getApplicationContext());
				movieView.setAdapter(similarMovieAdapter);
			} catch(JSONException je) {
				je.printStackTrace();
			}
		}
	}

	// Load the actor data.
	private class ActorDetails extends AsyncTask<String, Void, String> {

		private final String API_KEY = ConfigHelper.getConfigValue(getApplicationContext(), "api_key");

		protected String doInBackground(String... params) {
			String line;
			StringBuilder stringBuilder = new StringBuilder();

			// Load the webpage with the actor's movies.
			try {
				URL url = new URL("https://api.themoviedb.org/3/person/" +
						actorId + "?api_key=" + API_KEY);
				URLConnection urlConnection = url.openConnection();

				try {
					BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(
						urlConnection.getInputStream()));

					// Create one long string of the webpage.
					while((line = bufferedReader.readLine()) != null) {
						stringBuilder.append(line).append("\n");
					}

					// Close connection and return the data from the webpage.
					bufferedReader.close();
					return stringBuilder.toString();
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			} catch(MalformedURLException mue) {
				mue.printStackTrace();
			} catch(IOException ioe) {
				ioe.printStackTrace();
			}

			// Loading the dataset failed, return null.
			return null;
		}

		protected void onPostExecute(String response) {
			// Send all the actor data to setActorData.
			try {
				JSONObject actorData = new JSONObject(response);
				setActorData(actorData);
			} catch(JSONException e) {
				e.printStackTrace();
			}
		}
	}
}
